package com.cloud.weixin.project.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.common.core.asserts.ApiAssert;
import com.cloud.common.core.enums.ErrorCodeEnum;
import com.cloud.weixin.handler.SubscribeHandler;
import com.cloud.weixin.project.cons.WxCons;
import com.cloud.weixin.project.mapper.WxUserMapper;
import com.cloud.weixin.project.model.entity.WxUser;
import com.cloud.weixin.project.service.IWxUserService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.api.WxMpUserTagService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 微信用户 服务实现类
 * </p>
 *
 * @author Sam
 * @since 2021-04-26
 */
@Slf4j
@Service
public class WxUserServiceImpl extends ServiceImpl<WxUserMapper, WxUser> implements IWxUserService {

    @Autowired
    private WxMpService wxMpService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sync() throws WxErrorException {
        //先将已关注的用户取关
        this.update(Wrappers.<WxUser>lambdaUpdate()
                .set(WxUser::getSubscribe, WxCons.SUBSCRIBE_TYPE_NO)
                .eq(WxUser::getSubscribe, WxCons.SUBSCRIBE_TYPE_YES));
        String accessToken = wxMpService.getAccessToken();
        System.out.println("accessToken = " + accessToken);
        WxMpUserService wxMpUserService = wxMpService.getUserService();
        this.recursionGet(wxMpUserService, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRemark(String id, String remark) {
        WxUser user = this.getById(id);
        ApiAssert.notNull(ErrorCodeEnum.BAD_SELECT_FAILURE, user);
        String openId = user.getOpenId();
        WxUser updateWxUser = new WxUser();
        updateWxUser.setId(id);
        updateWxUser.setRemark(remark);
        ApiAssert.isTrue(ErrorCodeEnum.BAD_UPDATE_FAILURE, this.updateById(updateWxUser));
        WxMpUserService wxMpUserService = wxMpService.getUserService();
        try {
            wxMpUserService.userUpdateRemark(openId, remark);
        } catch (WxErrorException e) {
            ApiAssert.failure(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("修改微信用户备注失败，请检查参数/配置信息"), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tagging(String taggingType, Long tagId, Set<String> openIdSet) throws WxErrorException {
        WxMpUserTagService wxMpUserTagService = wxMpService.getUserTagService();
        WxUser wxUser;
        if ("tagging".equals(taggingType)) {
            for (String openId : openIdSet) {
                wxUser = this.getOne(Wrappers.<WxUser>lambdaQuery()
                        .eq(WxUser::getOpenId, openId), false);
                ApiAssert.notNull(ErrorCodeEnum.BAD_SELECT_FAILURE, wxUser);
                List<Long> tagIdList = JSONArray.parseArray(wxUser.getTagIdList(), Long.class);
                if (!tagIdList.contains(tagId)) {
                    tagIdList.add(tagId);
                    wxUser.setTagIdList(tagIdList.toString());
                    this.updateById(wxUser);
                }
            }
            wxMpUserTagService.batchTagging(tagId, openIdSet.toArray(new String[0]));
        }
        if ("unTagging".equals(taggingType)) {
            for (String openId : openIdSet) {
                wxUser = this.getOne(Wrappers.<WxUser>lambdaQuery()
                        .eq(WxUser::getOpenId, openId), false);
                ApiAssert.notNull(ErrorCodeEnum.BAD_SELECT_FAILURE, wxUser);
                List<Long> tagIdList = JSONArray.parseArray(wxUser.getTagIdList(), Long.class);
                if (tagIdList.contains(tagId)) {
                    tagIdList.remove(tagId);
                    wxUser.setTagIdList(tagIdList.toString());
                    this.updateById(wxUser);
                }
            }
            wxMpUserTagService.batchUntagging(tagId, openIdSet.toArray(new String[0]));
        }
    }

    /**
     * 递归获取
     *
     * @param nextOpenid
     */
    void recursionGet(WxMpUserService wxMpUserService, String nextOpenid) throws WxErrorException {
        WxMpUserList userList = wxMpUserService.userList(nextOpenid);
        List<WxUser> listWxUser = new ArrayList<>();
        List<WxMpUser> listWxMpUser = getWxMpUserList(wxMpUserService, userList.getOpenids());
        listWxMpUser.forEach(wxMpUser -> {
            WxUser wxUser = this.getOne(Wrappers.<WxUser>lambdaQuery()
                    .eq(WxUser::getOpenId, wxMpUser.getOpenId()), false);
            if (wxUser == null) {//用户未存在
                wxUser = new WxUser();
                wxUser.setSubscribeNum(1);
            }
            SubscribeHandler.setWxUserValue(wxUser, wxMpUser);
            listWxUser.add(wxUser);
        });
        this.saveOrUpdateBatch(listWxUser);
        if (userList.getCount() >= 10000) {
            this.recursionGet(wxMpUserService, userList.getNextOpenid());
        }
    }

    /**
     * 分批次获取微信粉丝信息 每批100条
     *
     * @param wxMpUserService
     * @param openidsList
     * @return
     * @throws WxErrorException
     * @author
     */
    private List<WxMpUser> getWxMpUserList(WxMpUserService wxMpUserService, List<String> openidsList) throws WxErrorException {
        // 粉丝openid数量
        int count = openidsList.size();
        if (count <= 0) {
            return new ArrayList<>();
        }
        List<WxMpUser> list = Lists.newArrayList();
        List<WxMpUser> followersInfoList;
        int a = count % 100 > 0 ? count / 100 + 1 : count / 100;
        for (int i = 0; i < a; i++) {
            if (i + 1 < a) {
                followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, ((i + 1) * 100)));
                if (null != followersInfoList && !followersInfoList.isEmpty()) {
                    list.addAll(followersInfoList);
                }
            } else {
                followersInfoList = wxMpUserService.userInfoList(openidsList.subList(i * 100, count));
                if (null != followersInfoList && !followersInfoList.isEmpty()) {
                    list.addAll(followersInfoList);
                }
            }
        }
        log.debug("本批次获取微信粉丝数：", list.size());
        return list;
    }
}
